﻿using System;
using System.Reflection;

namespace Utils
{
    public static class BeanUtil
    {
        /// <summary>
        /// 将源对象的所有属性值拷贝到目标对象的同名属性中。
        /// 不同名的属性不进行操作，同名但是有一方为枚举类型则进行枚举与值之间的转换，
        /// 若无法实现转换则不进行操作。如果类型不同，名称相同，并且目标类型为数组类型，则通过JSON转换的方式转换为对应类型的数组。
        /// </summary>
        /// <param name="source">源对象</param>
        /// <param name="target">目标对象</param>
        public static void CopyProperties(object source, object target)
        {
            if (source == null || target == null)
            {
                return;
            }

            Type sourceType = source.GetType();
            Type targetType = target.GetType();

            PropertyInfo[] sourceProperties = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            PropertyInfo[] targetProperties = targetType.GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (PropertyInfo sourceProperty in sourceProperties)
            {
                foreach (PropertyInfo targetProperty in targetProperties)
                {
                    if (sourceProperty.Name == targetProperty.Name && targetProperty.CanWrite)
                    {
                        try
                        {
                            object sourceValue = sourceProperty.GetValue(source);
                            if (sourceValue == null)
                            {
                                targetProperty.SetValue(target, null);
                                continue;
                            }

                            if (sourceProperty.PropertyType.IsEnum && !targetProperty.PropertyType.IsEnum)
                            {
                                // 源是枚举，目标不是枚举，尝试转换为目标类型的值
                                object convertedValue = Convert.ChangeType(Convert.ChangeType(sourceValue, Enum.GetUnderlyingType(sourceProperty.PropertyType)), targetProperty.PropertyType);
                                targetProperty.SetValue(target, convertedValue);
                            }
                            else if (!sourceProperty.PropertyType.IsEnum && targetProperty.PropertyType.IsEnum)
                            {
                                // 源不是枚举，目标是枚举，尝试转换为目标枚举类型
                                object convertedValue = Enum.ToObject(targetProperty.PropertyType, sourceValue);
                                targetProperty.SetValue(target, convertedValue);
                            }
                            else if (sourceProperty.PropertyType == targetProperty.PropertyType)
                            {
                                // 类型相同，直接赋值
                                targetProperty.SetValue(target, sourceValue);
                            }
                        }
                        catch (Exception)
                        {
                            // 转换失败，不进行操作
                        }
                    }
                }
            }
        }
    }
}
